package com.qf.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.qf.constant.Constant;
import com.qf.entity.Email;
import com.qf.entity.User;
import com.qf.result.ResultCheckData;
import com.qf.result.ResultMsg;
import com.qf.service.ICartService;
import com.qf.service.IUserService;
import com.qf.utils.CodeUtils;
import lombok.extern.slf4j.Slf4j;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import sun.security.util.Password;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @Author：刘亚康
 * @Date：2020/4/7
 * @QQ：50770284
 * @Phone：18235947935
 * @Desc :
 **/
@Slf4j
@Controller
@RequestMapping("sso")
public class SSOController {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @Reference
    private IUserService userService;

    @Reference
    private ICartService cartService;
    /**
     * ajax验证邮箱唯一
     * @param param
     * @return
     */
    @RequestMapping("checkEmailIsOne")
    @ResponseBody
    public ResultCheckData checkEmail(String param){
        log.info("需要验证的邮箱为："+param);
        User user=userService.CheckEmail(param);
        if (user!=null) {
            log.info("邮箱："+param+"已存在");
            return ResultCheckData.mailFail();
        }else {
            log.info("邮箱："+param+"不存在");
            return ResultCheckData.mailSuccess();
        }


    }

    /**
     * ajax验证用户名唯一
     * @param param
     * @return
     */
    @RequestMapping("checkUsernameIsOne")
    @ResponseBody
    private ResultCheckData checkUsernameIsOne(String param){
        log.info("需要验证的用户名为："+param);
        User user=userService.checkUsernameIsOne(param);
        if (user!=null) {
            log.info("用户名："+param+"已存在");
            return ResultCheckData.usernameFail();
        }else {
            log.info("用户名："+param+"不存在");
            return ResultCheckData.usernameSuccess();
        }
    }

    @RequestMapping("checkEmailCode")
    @ResponseBody
    public void checkEmailCode(String emailStr){
        log.info("邮箱："+emailStr+"需要发送验证码");
        Email email = new Email();
        email.setTitle("商城验证码");
        String code=CodeUtils.getCode();
        log.info("获取到的验证码为："+code);

        email.setContent("您的验证码为："+code+"，有效时间 5 分钟，官方不会以任何理由向您索要验证码，请不要泄露给其他人！");
        email.setTo(emailStr);
        //通过RabbitMQ发送验证码
        rabbitTemplate.convertAndSend("emailExchange","",email);
        //将验证码写入Redis,设置有效时间为300s
        redisTemplate.opsForValue().set(emailStr+ Constant.EMAIL_CODE,code,300, TimeUnit.SECONDS);
    }

    /**
     * 用户注册
     * @param user
     * @param code
     * @return
     */
    @RequestMapping("register")
    @ResponseBody
    public ResultMsg register(User user,String code){
        log.info("注册的用户为："+user+"验证码为："+code);
        //从Redis中获取Code判断是否有效
        String redisCode = (String) redisTemplate.opsForValue().get(user.getEmail() + Constant.EMAIL_CODE);
        log.info("从Redis中获取的验证码为："+redisCode);
        if (redisCode!=null) {
            log.info(user.getEmail()+"验证码存在且有效");
            //判断验证码是否一致
            if (redisCode.equals(code)) {
                log.info(user.getEmail()+"验证码校验通过");
                //添加用户
                int resultAdd = userService.add(user);
                if (resultAdd>0) {
                    log.info("注册成功，请登录！");
                    return ResultMsg.successMsg("注册成功，请登录！");
                }else {
                    log.info("未知原因，注册失败，请联系管理员");
                    return ResultMsg.fail("未知原因，注册失败，请联系管理员");
                }
            }else {
                log.info(user.getEmail()+"验证码输入错误");
                return ResultMsg.fail("验证码输入错误");
            }
        }else {
            log.info(user.getEmail()+"验证码失效");
            return ResultMsg.fail("验证码不存在或失效");
        }


    }

    /**
     * 判断用户名是否存在
     * @param param
     * @return
     */
    @RequestMapping("checkUsername")
    @ResponseBody
    public ResultCheckData checkUsername(String param){
        log.info("需要验证的用户名为："+param);
        User user = userService.checkUsernameIsOne(param);
        if (user!=null) {
            log.info("用户名："+param+"存在");
            return ResultCheckData.SUCCESS_MSG("用户名存在");
        }else {
            log.info("用户名："+param+"不存在");
            return ResultCheckData.FAIL_MSG("用户名不存在");
        }
    }

    /**
     * 通过用户名来发送找回密码邮件
     * @param username
     * @return
     */
    @RequestMapping("findPassword")
    @ResponseBody
    public ResultMsg findPassword(String username){
        log.info("需要修改密码的用户名为："+username);
        User user = userService.checkUsernameIsOne(username);
        //加入验证字符
        String token= UUID.randomUUID().toString();

        //找回密码连接
        String findPasswordUrl="http://localhost:8085/findPasswordInput?username="+username+"&token="+token;

        //发送邮件
        Email email=new Email();
        String userEmail = user.getEmail();

        email.setTo(userEmail);
        email.setTitle("商城找回密码");
        email.setContent("您的找回密码链接："+findPasswordUrl+"，链接有效时间5分钟，且只可修改一次！修改完成后请妥善保存您的密码！如若无法跳转，请复制链接到地址栏中访问！");
        //通过RabbitMQ发送邮件
        rabbitTemplate.convertAndSend("emailExchange","",email);
        //将Token存入Redis并设置时间来判断
        redisTemplate.opsForValue().set(username+Constant.PASSWORD_TOKEN,token,5,TimeUnit.MINUTES);

        //混淆真实邮箱
        String tempEmail=userEmail.replace(userEmail.substring(4,userEmail.indexOf("@")),"*****");
        //获取登陆邮箱网址
        String toEmailHost=userEmail.replace(userEmail.substring(0,userEmail.indexOf("@")+1),"email.");

        return ResultMsg.successMsg("修改密码链接已发送至注册时绑定邮箱：【"+tempEmail+"】请点击 <a href='http://"+toEmailHost+"' target='_blank' style='color: blue'>登陆邮箱</a> 查看");
    }

    /**
     * 重置密码
     * @param user
     * @param token
     * @return
     */
    @RequestMapping("findPasswordUpdate")
    @ResponseBody
    public ResultMsg findPasswordUpdate(User user,String token){
        log.info("需要重置密码的用户信息"+user+"token为："+token);
        User updateUser = userService.checkUsernameIsOne(user.getUsername());
        String redisToken = (String) redisTemplate.opsForValue().get(user.getUsername() + Constant.PASSWORD_TOKEN);
        if (redisToken!=null) {
            if (redisToken.equals(token)) {

                updateUser.setPassword(user.getPassword());
                int resultUpdate = userService.update(updateUser);
                if (resultUpdate>0) {
                    log.info(user.getUsername()+"密码修改成功");

                    //删除redis key
                    redisTemplate.delete(user.getUsername()+Constant.PASSWORD_TOKEN);
                    return ResultMsg.successMsg("密码重置成功，请登录");
                }else{
                    log.info(user.getUsername()+"密码修改失败，未知异常");
                    return ResultMsg.fail("未知异常，密码修改失败，请联系管理员");
                }
            }else {
                log.info(updateUser.getEmail()+"Token不匹配");
                return ResultMsg.fail("链接失效，请重新获取");
            }

        }else {
            log.info(updateUser.getEmail()+"Token失效");
            return ResultMsg.fail("链接失效，请重新获取");
        }

    }

    /**
     * 登陆操作
     * @param username
     * @param password
     * @return
     */
    @RequestMapping("login")
    @ResponseBody
    public ResultMsg login(String username, String password,String returnUrl, HttpServletResponse response,@CookieValue(name = Constant.CART_TOKEN,required = false)String cartToken){
        User loginUser = userService.checkUsernameIsOne(username);
        log.info("要返回的URL"+returnUrl);
        if (loginUser!=null) {
            log.info(username+"请求登陆");
            if (password.equals(loginUser.getPassword())) {
                log.info(username+"登陆成功");
                //合并购物车
                if (!StringUtils.isEmpty(cartToken)) {
                    cartService.mergeCart(loginUser,cartToken);
                }
                loginUser.setPassword("");
                //将token保存在Redis中,并保存一周
                redisTemplate.opsForValue().set(username+Constant.LOGIN_TOKEN,loginUser,7,TimeUnit.DAYS);
                Cookie cookie = new Cookie(Constant.LOGIN_TOKEN,username);
                cookie.setMaxAge(60*60*24*7);//设置cookie时间
                cookie.setHttpOnly(false);//不允许JS访问
                cookie.setPath("/");//同域名下可跨域
                //cookie.setDomain("");支持正则的跨域名
                //cookie.setSecure();安全访问，HTTPS

                response.addCookie(cookie);
                if (StringUtils.isEmpty(returnUrl)){
                    returnUrl="http://localhost:8083";
                }

                return ResultMsg.success("登陆成功",returnUrl);
            }else {
                log.info("用户名或密码错误，登陆失败");
                return ResultMsg.fail("用户名或密码错误，登陆失败");
            }
        }else {
            log.info("账号不存在");
            return ResultMsg.fail("用户名不存在");
        }
    }

    /**
     * 其他页面携带token判断登陆状态
     * @param callback
     * @param loginToken
     * @return
     */
    @RequestMapping("isLogin")
    @ResponseBody
    public String isLogin(String callback,@CookieValue(name = Constant.LOGIN_TOKEN,required = false) String loginToken){
        log.info(loginToken+"判断登陆");
        String userJson="";
        if (!StringUtils.isEmpty(loginToken)) {

            User user = (User) redisTemplate.opsForValue().get(loginToken + Constant.LOGIN_TOKEN);
            userJson = JSON.toJSONString(user);
        }


        //支持Jsonp，也支持非JsonP
        return callback==null?userJson:callback+"('"+userJson+"')";
    }
    @RequestMapping("logout")
    public String logout(@CookieValue(name = Constant.LOGIN_TOKEN,required = false) String loginToken,HttpServletResponse resp){
        log.info(loginToken+"退出");
//        if (!StringUtils.isEmpty(loginToken)) {
            //删除redis中的key
            Boolean deleteResult = redisTemplate.delete(loginToken + Constant.LOGIN_TOKEN);
            //删除cookie
            Cookie cookie = new Cookie(Constant.LOGIN_TOKEN,"");
            cookie.setMaxAge(-1);
            cookie.setPath("/");
            cookie.setHttpOnly(false);

            resp.addCookie(cookie);

//            if (deleteResult) {
//                log.info(loginToken+"登出成功");
//                return ResultMsg.success("注销成功","http://localhost:8083");
//            }else {
//                log.info(loginToken+"删除失败");
//                return ResultMsg.fail("未知异常，请联系管理员");
//            }
//        }else {
//            log.info(loginToken+"为空");
//            return ResultMsg.fail("当前未登陆，请先登陆");
//        }
        return "redirect:http://localhost:8085/toLogin";
    }
}
